﻿// OptionBytesDlg.cpp: 实现文件
//

#include "pch.h"
#include "PY32IspTool.h"
#include "OptionBytesDlg.h"
#include "afxdialogex.h"
#include "data_handle_macro.h"

typedef struct _T_MCU
{
	CString name;
	WORD id;
}T_MCU;

typedef enum _E_PROJECT_ID
{
	PT061 = 0x0440,
	PT063 = 0x0448,
	PT064 = 0x0064,
	PT067 = 0x0444,
	PT068 = 0x0068,
	PT100 = 0x0413
}E_PROJECT_ID;

const T_MCU MCU_LIST[] = {
	{_T("PY32C610"), PT061},
	{_T("PY32C611"), PT061},
	{_T("PY32C640"), PT064},
	{_T("PY32C641"), PT064},
	{_T("PY32C670"), PT067},
	{_T("PY32F001"), PT064},
	{_T("PY32F002A"), PT061},
	{_T("PY32F002B"), PT064},
	{_T("PY32F003"), PT061},
	{_T("PY32F030"), PT061},
	{_T("PY32F031"), PT067},
	{_T("PY32F040"), PT063},
	{_T("PY32F071"), PT063},
	{_T("PY32F072"), PT063},
	{_T("PY32F303"), PT100},
	{_T("PY32F403"), PT100},
	{_T("PY32L020"), PT064},
	{_T("PY32M010"), PT064},
	{_T("PY32M030"), PT061},
	{_T("PY32M070"), PT063},
	{_T("PY32T020"), PT068},
};

CONST UINT MCU_LIST_SIZE = 21;
CONST UINT DEFAULT_MCU_SEL = 9;

// COptionBytesDlg 对话框

IMPLEMENT_DYNAMIC(COptionBytesDlg, CDialogEx)

COptionBytesDlg::COptionBytesDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_OPTION_BYTES, pParent)
{

}

COptionBytesDlg::~COptionBytesDlg()
{
}

void COptionBytesDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(COptionBytesDlg, CDialogEx)
	ON_WM_CREATE()
	ON_BN_CLICKED(IDOK, &COptionBytesDlg::OnBnClickedOk)
END_MESSAGE_MAP()


// COptionBytesDlg 消息处理程序
void COptionBytesDlg::AdjustLayout()
{
	if (GetSafeHwnd() == nullptr || (AfxGetMainWnd() != nullptr && AfxGetMainWnd()->IsIconic()))
	{
		return;
	}

	CRect rectClient;
	GetClientRect(rectClient);

	m_wndPropList.SetWindowPos(nullptr, rectClient.left + 5, rectClient.top + 5, rectClient.Width() - 10, rectClient.Height() - 50, SWP_NOACTIVATE | SWP_NOZORDER);

	HDITEM hdItem;
	hdItem.mask = HDI_WIDTH;
	hdItem.cxy = m_wndPropList.GetListRect().Width() / 4;
	m_wndPropList.GetHeaderCtrl().SetItem(0, &hdItem);
}

void COptionBytesDlg::SetPropListFont()
{
	::DeleteObject(m_fntPropList.Detach());

	LOGFONT lf;
	afxGlobalData.fontRegular.GetLogFont(&lf);

	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);

	afxGlobalData.GetNonClientMetrics(info);

	lf.lfHeight = info.lfMenuFont.lfHeight;
	lf.lfWeight = info.lfMenuFont.lfWeight;
	lf.lfItalic = info.lfMenuFont.lfItalic;

	m_fntPropList.CreateFontIndirect(&lf);

	m_wndPropList.SetFont(&m_fntPropList);
}

int COptionBytesDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDialogEx::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	CRect rectDummy;
	rectDummy.SetRectEmpty();

	if (!m_wndPropList.Create(WS_VISIBLE | WS_CHILD, rectDummy, this, 2))
	{
		TRACE0("未能创建属性网格\n");
		return -1;      // 未能创建
	}

	InitPropList();

	AdjustLayout();

	return 0;
}

CONST COleVariant RDP_STR[] = { _T("0xAA: level 0, read protection inactive"), _T("0x55: level 1, read protection active") };
CONST COleVariant IWDG_SW_STR[] = { _T("0: hardware watchdog"), _T("1: software watchdog") };
CONST COleVariant nRST_STOP_STR[] = { _T("0: reset generated when entering Stop mode"), _T("1: no reset generated") };
CONST COleVariant nRST_STDBY_STR[] = { _T("0: reset generated when entering Standby mode"), _T("1: no reset generated") };
CONST COleVariant WRP_STR[] = { _T("0: Write Protection"), _T("1: No Write Protection") };

CONST COleVariant WWDG_SW_STR[] = { _T("0: hardware watchdog"), _T("1: software watchdog") };
CONST COleVariant NRST_MODE_STR[] = { _T("0: RST"), _T("1: GPIO") };
CONST COleVariant nBOOT1_STR[] = { _T("0: boot from SRAM when BOOT0=1"), _T("1: boot from SYSTEM when BOOT0=1") };
CONST COleVariant IWDG_STOP_STR[] = { _T("0: freze TIMER"), _T("1: RUN") };

CONST COleVariant BOR_EN_STR[] = { _T("0: BOR Disable"), _T("1: BOR Enable") };
CONST COleVariant BOR_LEV_STR[] = { _T("000: rise threshold is 1.8V, descent threshold is 1.7V"),
									_T("001: rise threshold is 2.0V, descent threshold is 1.9V"),
									_T("010 : rise threshold is 2.2V, descent threshold is 2.1V"),
									_T("011 : rise threshold is 2.4V, descent threshold is 2.3V"),
									_T("100 : rise threshold is 2.6V, descent threshold is 2.5V"),
									_T("101 : rise threshold is 2.8V, descent threshold is 2.7V"),
									_T("110 : rise threshold is 3.0V, descent threshold is 2.9V"),
									_T("111 : rise threshold is 3.2V, descent threshold is 3.1V") };

CONST COleVariant NRST_SWD_MODE_STR[] = { _T("00：PCO：NRST PB6：SWD"),
										  _T("01：PCO：NRST PB6：SWD"),
										  _T("10：PCO：GPIO PB6：SWD"),
										  _T("11：PCO：SWD  PB6：GPIO") };
CONST COleVariant BOOT_SIZE_STR[] = { _T("000：0Kbytes"),
									  _T("001：1Kbytes（0x0800 5C00~0x0800 5FFF）"),
									  _T("010：2Kbytes（0x0800 5800~0x0800 5FFF）"),
									  _T("011：3Kbytes（0x0800 5400~0x0800 5FFF）"),
									  _T("100：4Kbytes（0x0800 5000~0x0800 5FFF）"),
									  _T("101：4Kbytes（0x0800 5000~0x0800 5FFF）"),
									  _T("110：4Kbytes（0x0800 5000~0x0800 5FFF）"),
									  _T("111：4Kbytes（0x0800 5000~0x0800 5FFF）") };
CONST COleVariant nBOOT1_BOOT0_STR[] = { _T("00：MainFlash Boot"),
										 _T("01：SRAM Boot"),
										 _T("10：MainFlash Boot"),
										 _T("11：Load Flash Boot") };
CONST COleVariant SWD_MODE_STR[] = { _T("00：SWCLK(PF3), SWDIO(PF4)"),
									 _T("01：SWCLK(PA14), SWDIO(PA13)"),
									 _T("10：SWCLK(PA14), SWDIO(PF4)"),
									 _T("11：SWCLK(PF3), SWDIO(PA13)") };


void COptionBytesDlg::InitPropList()
{
	UINT nValue, nItem = 0;
	CString strName, strDescr;	

	SetPropListFont();

	m_wndPropList.EnableHeaderCtrl(TRUE, _T("Name"), _T("Function"));
	m_wndPropList.EnableDescriptionArea();
	m_wndPropList.SetVSDotNetLook();
	m_wndPropList.MarkModifiedProperties();

	CMFCPropertyGridProperty* pGroup;

	switch (m_wPID)
	{
	case PT068:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << 0) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_EN"), BOR_EN_STR[nValue], _T("[Bits 8] RW (@ 0x40022020) desc BOR_EN"));
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x01], 0x7 << (9 - 8)) >> (9 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_LEV"), BOR_LEV_STR[nValue], _T("[Bits 11...9] RW (@ 0x40022020) desc BOR_LEV"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOR_LEV_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (14 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("NRST_MODE"), NRST_MODE_STR[nValue], _T("[Bits 14] RW (@ 0x40022020) desc NRST_MODE"));
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (15 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_STOP"), IWDG_STOP_STR[nValue], _T("[Bits 15] RW (@ 0x40022020) desc IWDG_STOP"));
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash SDK area address"));
		nValue = (READ_BIT(m_pucOptionBytes[0x04], 0x0F << 0) >> 0);
		strName.Format(_T("0x%08X"), (nValue + 0) * 2 * 0x400);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_STRT"), strName, _T("[Bits 3...0] RW (@ 0x40022024) desc SDK_STRT"));
		for (UINT i = 0; i < 32 / 2; i++) {
			strName.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x05], 0x0F << (8 - 8)) >> (8 - 8));
		strName.Format(_T("0x%08X"), (nValue + 1) * 2 * 0x400 - 1);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_END"), strName, _T("[Bits 11...8] RW (@ 0x40022024) desc SDK_END"));
		for (UINT i = 0; i < 32 / 2; i++) {
			strName.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for boot control"));
		nValue = (READ_BIT(m_pucOptionBytes[0x08], 0x7 << 0) >> 0);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOOT_SIZE"), BOOT_SIZE_STR[nValue], _T("[Bits 2...0] RW (@ 0x40022028) desc BOOT_SIZE"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOOT_SIZE_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x3 << (8 - 8)) >> (8 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SWD_MODE"), SWD_MODE_STR[nValue], _T("[Bits 9...8] RW (@ 0x40022028) desc BOOT_SIZE"));
		for (UINT i = 0; i < 4; i++) {
			m_pPropertyItem[nItem]->AddOption(SWD_MODE_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x3 << (14 - 8)) >> (14 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nBOOT1_BOOT0"), nBOOT1_BOOT0_STR[nValue], _T("[Bits 15...14] RW (@ 0x40022028) desc nBOOT1_BOOT0"));
		for (UINT i = 0; i < 4; i++) {
			m_pPropertyItem[nItem]->AddOption(nBOOT1_BOOT0_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 32 / 4; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 4 * 0x400, 0x08000000 + (i + 1) * 4 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	case PT064:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		//nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		//m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		//m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		//m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		//m_pPropertyItem[nItem]->AllowEdit(FALSE);
		//pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << 0) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_EN"), BOR_EN_STR[nValue], _T("[Bits 8] RW (@ 0x40022020) desc BOR_EN"));
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x01], 0x7 << (9 - 8)) >> (9 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_LEV"), BOR_LEV_STR[nValue], _T("[Bits 11...9] RW (@ 0x40022020) desc BOR_LEV"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOR_LEV_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x01], 0x3 << (13 - 8)) >> (13 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("NRST_SWD_MODE"), NRST_SWD_MODE_STR[nValue], _T("[Bits 14...13] RW (@ 0x40022020) desc NRST_SWD_MODE"));
		m_pPropertyItem[nItem]->AddOption(NRST_SWD_MODE_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_SWD_MODE_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_SWD_MODE_STR[2].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_SWD_MODE_STR[3].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (15 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_STOP"), IWDG_STOP_STR[nValue], _T("[Bits 15] RW (@ 0x40022020) desc IWDG_STOP"));
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash SDK area address"));
		nValue = (READ_BIT(m_pucOptionBytes[0x04], 0x0F << 0) >> 0);
		strName.Format(_T("0x%08X"), (nValue + 0) * 2 * 0x400);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_STRT"), strName, _T("[Bits 3...0] RW (@ 0x40022024) desc SDK_STRT"));
		for (UINT i = 0; i < 0x0C; i++) {
			strName.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x05], 0x0F << (8 - 8)) >> (8 - 8));
		strName.Format(_T("0x%08X"), (nValue + 1) * 2 * 0x400 - 1);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_END"), strName, _T("[Bits 11...8] RW (@ 0x40022024) desc SDK_END"));
		for (UINT i = 0; i < 0x0C; i++) {
			strName.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for boot control"));
		nValue = (READ_BIT(m_pucOptionBytes[0x08], 0x7 << 0) >> 0);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOOT_SIZE"), BOOT_SIZE_STR[nValue], _T("[Bits 2...0] RW (@ 0x40022028) desc BOOT_SIZE"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOOT_SIZE_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x3 << (14 - 8)) >> (14 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nBOOT1_BOOT0"), nBOOT1_BOOT0_STR[nValue], _T("[Bits 15...14] RW (@ 0x40022028) desc nBOOT1_BOOT0"));
		for (UINT i = 0; i < 4; i++) {
			m_pPropertyItem[nItem]->AddOption(nBOOT1_BOOT0_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 24 / 4; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 4 * 0x400, 0x08000000 + (i + 1) * 4 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	case PT061:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (8 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_EN"), BOR_EN_STR[nValue], _T("[Bits 8] RW (@ 0x40022020) desc BOR_EN"));
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x01], 0x7 << (9 - 8)) >> (9 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_LEV"), BOR_LEV_STR[nValue], _T("[Bits 11...9] RW (@ 0x40022020) desc BOR_LEV"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOR_LEV_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (13 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("WWDG_SW"), WWDG_SW_STR[nValue], _T("[Bits 13] RW (@ 0x40022020) desc WWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (14 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("NRST_MODE"), NRST_MODE_STR[nValue], _T("[Bits 14] RW (@ 0x40022020) desc NRST_MODE"));
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (15 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nBOOT1"), nBOOT1_STR[nValue], _T("[Bits 15] RW (@ 0x40022020) desc nBOOT1"));
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash SDK area address"));
		nValue = (READ_BIT(m_pucOptionBytes[0x04], 0x1F << 0) >> 0);
		strName.Format(_T("0x%08X"), (nValue + 0) * 2 * 0x400);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_STRT"), strName, _T("[Bits 4...0] RW (@ 0x40022024) desc SDK_STRT"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x05], 0x1F << (8 - 8)) >> (8 - 8));
		strName.Format(_T("0x%08X"), (nValue + 1) * 2 * 0x400 - 1);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_END"), strName, _T("[Bits 12...8] RW (@ 0x40022024) desc SDK_END"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 64 / 4; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 4 * 0x400, 0x08000000 + (i + 1) * 4 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	case PT067:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);

		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (11 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_STOP"), IWDG_STOP_STR[nValue], _T("[Bits 11] RW (@ 0x40022020) desc IWDG_STOP"));
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (13 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("WWDG_SW"), WWDG_SW_STR[nValue], _T("[Bits 13] RW (@ 0x40022020) desc WWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (14 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("NRST_MODE"), NRST_MODE_STR[nValue], _T("[Bits 14] RW (@ 0x40022020) desc NRST_MODE"));
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (15 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nBOOT1"), nBOOT1_STR[nValue], _T("[Bits 15] RW (@ 0x40022020) desc nBOOT1"));
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		nValue = READ_BIT(m_pucOptionBytes[0x04], 1 << (16 - 16)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_EN"), BOR_EN_STR[nValue], _T("[Bits 16] RW (@ 0x40022020) desc BOR_EN"));
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x04], 0x7 << (17 - 16)) >> (17 - 16));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_LEV"), BOR_LEV_STR[nValue], _T("[Bits 19...17] RW (@ 0x40022020) desc BOR_LEV"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOR_LEV_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash SDK area address"));
		nValue = (READ_BIT(m_pucOptionBytes[0x08], 0x1F << 0) >> 0);
		strName.Format(_T("0x%08X"), (nValue + 0) * 2 * 0x400);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_STRT"), strName, _T("[Bits 4...0] RW (@ 0x40022024) desc SDK_STRT"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x1F << (8 - 8)) >> (8 - 8));
		strName.Format(_T("0x%08X"), (nValue + 1) * 2 * 0x400 - 1);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_END"), strName, _T("[Bits 12...8] RW (@ 0x40022024) desc SDK_END"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 64 / 4; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 4 * 0x400, 0x08000000 + (i + 1) * 4 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	case PT063:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (11 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 11] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("WWDG_SW"), WWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc WWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(WWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (13 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("NRST_MODE"), NRST_MODE_STR[nValue], _T("[Bits 13] RW (@ 0x40022020) desc NRST_MODE"));
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(NRST_MODE_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (14 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nBOOT1"), nBOOT1_STR[nValue], _T("[Bits 14] RW (@ 0x40022020) desc nBOOT1"));
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(nBOOT1_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (15 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_STOP"), IWDG_STOP_STR[nValue], _T("[Bits 15] RW (@ 0x40022020) desc IWDG_STOP"));
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_STOP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash SDK area address"));
		nValue = READ_BIT(m_pucOptionBytes[0x08], 1 << 5) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_EN"), BOR_EN_STR[nValue], _T("[Bits 5] RW (@ 0x40022024) desc BOR_EN"));
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(BOR_EN_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x7 << (13 - 8)) >> (13 - 8));
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("BOR_LEV"), BOR_LEV_STR[nValue], _T("[Bits 15...13] RW (@ 0x40022024) desc BOR_LEV"));
		for (UINT i = 0; i < 8; i++) {
			m_pPropertyItem[nItem]->AddOption(BOR_LEV_STR[i].bstrVal);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x08], 0x1F << 0) >> 0);
		strName.Format(_T("0x%08X"), (nValue + 0) * 4 * 0x400);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_STRT"), strName, _T("[Bits 4...0] RW (@ 0x40022024) desc SDK_STRT"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 0) * 4 * 0x400);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = (READ_BIT(m_pucOptionBytes[0x09], 0x1F << (8 - 8)) >> (8 - 8));
		strName.Format(_T("0x%08X"), (nValue + 1) * 4 * 0x400 - 1);
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("SDK_END"), strName, _T("[Bits 12...8] RW (@ 0x40022024) desc SDK_END"));
		for (UINT i = 0; i < 0x20; i++) {
			strName.Format(_T("0x%08X"), (i + 1) * 4 * 0x400 - 1);
			m_pPropertyItem[nItem]->AddOption(strName);
		}
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 128 / 8; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 8 * 0x400, 0x08000000 + (i + 1) * 8 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x18 + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[nItem]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	case PT100:
		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash User option"));
		nValue = (0xAA != m_pucOptionBytes[0x00]) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("RDP"), RDP_STR[nValue], _T("[Bits 7...0] RW (@ 0x40022020) desc RDP"));
		m_pPropertyItem[nItem]->AddOption(RDP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(RDP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (12 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("IWDG_SW"), IWDG_SW_STR[nValue], _T("[Bits 12] RW (@ 0x40022020) desc IWDG_SW"));
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(IWDG_SW_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (13 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nRST_STOP"), nRST_STOP_STR[nValue], _T("[Bits 13] RW (@ 0x40022020) desc nRST_STOP"));
		m_pPropertyItem[nItem]->AddOption(nRST_STOP_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(nRST_STOP_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		nValue = READ_BIT(m_pucOptionBytes[0x01], 1 << (14 - 8)) ? 1 : 0;
		m_pPropertyItem[nItem] = new CMFCPropertyGridProperty(_T("nRST_STDBY"), nRST_STDBY_STR[nValue], _T("[Bits 14] RW (@ 0x40022020) desc nRST_STDBY"));
		m_pPropertyItem[nItem]->AddOption(nRST_STDBY_STR[0].bstrVal);
		m_pPropertyItem[nItem]->AddOption(nRST_STDBY_STR[1].bstrVal);
		m_pPropertyItem[nItem]->AllowEdit(FALSE);
		pGroup->AddSubItem(m_pPropertyItem[nItem++]);
		m_wndPropList.AddProperty(pGroup);

		pGroup = new CMFCPropertyGridProperty(_T("Option byte for Flash WRP address"));
		for (DWORD i = 0; i < 384 / 32; i++) {
			strName.Format(_T("WRP[%d]"), i);
			strDescr.Format(_T("[Bits %d] RW (@ 0x4002202C) desc WRP\nWRP address: 0x%08X~0x%08X"), i, 0x08000000 + i * 32 * 0x400, 0x08000000 + (i + 1) * 32 * 0x400 - 1);
			nValue = READ_BIT(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8)) ? 1 : 0;
			m_pPropertyItem[i + 4] = new CMFCPropertyGridProperty(strName, WRP_STR[nValue], strDescr);
			m_pPropertyItem[i + 4]->AddOption(WRP_STR[0].bstrVal);
			m_pPropertyItem[i + 4]->AddOption(WRP_STR[1].bstrVal);
			pGroup->AddSubItem(m_pPropertyItem[i + 4]);
		}
		m_wndPropList.AddProperty(pGroup);
		break;
	}

}

void COptionBytesDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	UINT nItem = 0;
	COleVariant OleVariant;
	CString csValue;

	switch (m_wPID)
	{
	case PT068:
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << 0, (BOR_EN_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOR_LEV_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x01], 0x7 << (9 - 8), i << (9 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (14 - 8), (NRST_MODE_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (15 - 8), (IWDG_STOP_STR[1] == OleVariant));

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 32 / 4; i++) {
			csValue.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x04], 0x0F << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 32 / 4; i++) {
			csValue.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x05], 0x0F << (8 - 8), i << (8 - 8));
				break;
			}
		}

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOOT_SIZE_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x08], 0x7 << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 4; i++) {
			if (SWD_MODE_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x3 << (8 - 8), i << (8 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 4; i++) {
			if (nBOOT1_BOOT0_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x3 << (14 - 8), i << (14 - 8));
				break;
			}
		}

		for (DWORD i = 0; i < 32 / 4; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x06] = 0xFF - m_pucOptionBytes[0x04];
		m_pucOptionBytes[0x07] = 0xFF - m_pucOptionBytes[0x05];
		m_pucOptionBytes[0x0A] = 0xFF - m_pucOptionBytes[0x08];
		m_pucOptionBytes[0x0B] = 0xFF - m_pucOptionBytes[0x09];
		m_pucOptionBytes[0x0E] = 0xFF - m_pucOptionBytes[0x0C];
		m_pucOptionBytes[0x0F] = 0xFF - m_pucOptionBytes[0x0D];
		break;
	case PT064:
		//OleVariant = m_pPropertyItem[nItem++]->GetValue();
		//m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << 0, (BOR_EN_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOR_LEV_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x01], 0x7 << (9 - 8), i << (9 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 4; i++) {
			if (NRST_SWD_MODE_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x01], 0x3 << (13 - 8), i << (13 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (15 - 8), (IWDG_STOP_STR[1] == OleVariant));

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x0C; i++) {
			csValue.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x04], 0x0F << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x0C; i++) {
			csValue.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x05], 0x0F << (8 - 8), i << (8 - 8));
				break;
			}
		}

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOOT_SIZE_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x08], 0x7 << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 4; i++) {
			if (nBOOT1_BOOT0_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x3 << (14 - 8), i << (14 - 8));
				break;
			}
		}

		for (DWORD i = 0; i < 24 / 4; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x06] = 0xFF - m_pucOptionBytes[0x04];
		m_pucOptionBytes[0x07] = 0xFF - m_pucOptionBytes[0x05];
		m_pucOptionBytes[0x0A] = 0xFF - m_pucOptionBytes[0x08];
		m_pucOptionBytes[0x0B] = 0xFF - m_pucOptionBytes[0x09];
		m_pucOptionBytes[0x0E] = 0xFF - m_pucOptionBytes[0x0C];
		m_pucOptionBytes[0x0F] = 0xFF - m_pucOptionBytes[0x0D];
		break;
	case PT061:
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << 0, (BOR_EN_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOR_LEV_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x01], 0x7 << (9 - 8), i << (9 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (13 - 8), (WWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (14 - 8), (NRST_MODE_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (15 - 8), (nBOOT1_STR[1] == OleVariant));

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x04], 0x1F << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x05], 0x1F << (8 - 8), i << (8 - 8));
				break;
			}
		}

		for (DWORD i = 0; i < 64 / 4; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x06] = 0xFF - m_pucOptionBytes[0x04];
		m_pucOptionBytes[0x07] = 0xFF - m_pucOptionBytes[0x05];
		m_pucOptionBytes[0x0E] = 0xFF - m_pucOptionBytes[0x0C];
		m_pucOptionBytes[0x0F] = 0xFF - m_pucOptionBytes[0x0D];
		break;
	case PT067:
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (11 - 8), (IWDG_STOP_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (13 - 8), (WWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (14 - 8), (NRST_MODE_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (15 - 8), (nBOOT1_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x04], 1 << 0, (BOR_EN_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOR_LEV_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x04], 0x7 << (9 - 8), i << (9 - 8));
				break;
			}
		}

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 0) * 2 * 0x400);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x08], 0x1F << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 1) * 2 * 0x400 - 1);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x1F << (8 - 8), i << (8 - 8));
				break;
			}
		}

		for (DWORD i = 0; i < 64 / 4; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x06] = 0xFF - m_pucOptionBytes[0x04];
		m_pucOptionBytes[0x07] = 0xFF - m_pucOptionBytes[0x05];
		m_pucOptionBytes[0x0A] = 0xFF - m_pucOptionBytes[0x08];
		m_pucOptionBytes[0x0B] = 0xFF - m_pucOptionBytes[0x09];
		m_pucOptionBytes[0x0E] = 0xFF - m_pucOptionBytes[0x0C];
		m_pucOptionBytes[0x0F] = 0xFF - m_pucOptionBytes[0x0D];
		break;
	case PT063:
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (11 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (WWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (13 - 8), (NRST_MODE_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (14 - 8), (nBOOT1_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (15 - 8), (IWDG_STOP_STR[1] == OleVariant));

		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x08], 1 << 5, (BOR_EN_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 8; i++) {
			if (BOR_LEV_STR[i] == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x7 << (13 - 8), i << (13 - 8));
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 0) * 4 * 0x400);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x08], 0x1F << 0, i << 0);
				break;
			}
		}
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		for (UINT i = 0; i < 0x20; i++) {
			csValue.Format(_T("0x%08X"), (i + 1) * 4 * 0x400 - 1);
			if (csValue == OleVariant) {
				MODIFY_REG(m_pucOptionBytes[0x09], 0x1F << (8 - 8), i << (8 - 8));
				break;
			}
		}

		for (DWORD i = 0; i < 128 / 8; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x18 + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x0A] = 0xFF - m_pucOptionBytes[0x08];
		m_pucOptionBytes[0x0B] = 0xFF - m_pucOptionBytes[0x09];
		m_pucOptionBytes[0x1A] = 0xFF - m_pucOptionBytes[0x18];
		m_pucOptionBytes[0x1B] = 0xFF - m_pucOptionBytes[0x19];
		break;
	case PT100:
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		m_pucOptionBytes[0x00] = (RDP_STR[0] == OleVariant) ? 0xAA : 0x55;
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (12 - 8), (IWDG_SW_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (13 - 8), (nRST_STOP_STR[1] == OleVariant));
		OleVariant = m_pPropertyItem[nItem++]->GetValue();
		SET_BIT_DATA(m_pucOptionBytes[0x01], 1 << (14 - 8), (nRST_STDBY_STR[1] == OleVariant));
		for (DWORD i = 0; i < 384 / 32; i++) {
			OleVariant = m_pPropertyItem[nItem++]->GetValue();
			SET_BIT_DATA(m_pucOptionBytes[0x0C + (i / 8)], 1 << (i % 8), (WRP_STR[1] == OleVariant));
		}
		m_pucOptionBytes[0x02] = 0xFF - m_pucOptionBytes[0x00];
		m_pucOptionBytes[0x03] = 0xFF - m_pucOptionBytes[0x01];
		m_pucOptionBytes[0x0E] = 0xFF - m_pucOptionBytes[0x0C];
		m_pucOptionBytes[0x0F] = 0xFF - m_pucOptionBytes[0x0D];
		break;
	}

	CDialogEx::OnOK();
}
